/****************************************************
 * @file: main.c
 * @brief: 处理通信中的不同状态
 * @author: 廖文雄 
 * @date: 2019.07.27
 * @note: 
 ****************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <malloc.h>

#include "communication.h"

/*宏开关*/
#define TEST_FUNCTION           (0)
#define TEST_PROCESS            (1)

int main()
{
    /* 测试build_data和analysis_data函数 */
#if TEST_FUNCTION
    char *bag, origin_bag[7];
    int bag_type;

    /* 1.RESPONSE */
    origin_bag[0] = HEAD;
    origin_bag[1] = CODE_RESPONSE;
    origin_bag[3] = END;
    origin_bag[2] = origin_bag[0] - origin_bag[1] - origin_bag[3];
    origin_bag[4] = '\0';
    bag = build_data(RESPONSE);
    printf("RESPONSE:\n");
    printf("after build bag : %s\n", bag);
    printf("the effect you want to achieve:%s\n", origin_bag);
    if (!strcmp(bag, origin_bag)) {
        printf("RESPONSE match\n");
    }
    /*analysis_data*/
    printf("analysis_data\n");
    bag_type = analysis_data(bag);
    printf("ideal analysis result is %d\n", RESPONSE);
    printf("reality analysis result is %d\n\n", bag_type);

    /* 2.ACK_DATA */
    origin_bag[0] = HEAD;
    origin_bag[1] = CODE_ACK_DATA;
    origin_bag[3] = END;
    origin_bag[2] = origin_bag[0] - origin_bag[1] - origin_bag[3];
    origin_bag[4] = '\0';
    bag = build_data(ACK_DATA);
    printf("ACK_DATA:\n");
    printf("after build bag : %s\n", bag);
    printf("the effect you want to achieve:%s\n", origin_bag);
    if (!strcmp(bag, origin_bag)) {
        printf("ACK_DATA match\n");
    }
    /*analysis_data*/
    printf("analysis_data\n");
    bag_type = analysis_data(bag);
    printf("ideal analysis result is %d\n", ACK_DATA);
    printf("reality analysis result is %d\n\n", bag_type);

    /* 3.PRINT_NORMAL */
    origin_bag[0] = HEAD;
    origin_bag[1] = CODE_NORMAL;
    origin_bag[2] = 'h';
    origin_bag[3] = 'i';
    origin_bag[5] = END;
    origin_bag[4] = origin_bag[0] - origin_bag[1] - origin_bag[2] - origin_bag[3] -
                    origin_bag[5];
    origin_bag[6] = '\0';
    bag = build_data(PRINT_NORMAL);
    printf("PRINT_NORMAL:\n");
    printf("after build bag : %s\n", bag);
    printf("the effect you want to achieve:%s\n", origin_bag);
    if (!strcmp(bag, origin_bag)) {
        printf("PRINT_NORMAL match\n");
    }
    /*analysis_data*/
    printf("analysis_data\n");
    bag_type = analysis_data(bag);
    printf("ideal analysis result is %d\n", PRINT_NORMAL);
    printf("reality analysis result is %d\n\n", bag_type);

    /* 4.FALSE_DATA */
    origin_bag[0] = HEAD;
    origin_bag[1] = CODE_FALSE_DATA;
    origin_bag[3] = END;
    origin_bag[2] = origin_bag[0] - origin_bag[1] - origin_bag[3];
    origin_bag[4] = '\0';
    bag = build_data(FALSE_DATA);
    printf("FALSE_DATA:\n");
    printf("after build bag : %s\n", bag);
    printf("the effect you want to achieve:%s\n", origin_bag);
    if (!strcmp(bag, origin_bag)) {
        printf("FALSE_DATA match\n");
    }
    /*analysis_data*/
    printf("analysis_data\n");
    bag_type = analysis_data(bag);
    printf("ideal analysis result is %d\n", FALSE_DATA);
    printf("reality analysis result is %d\n\n", bag_type);

    /* 5.FALSE_REQUEST */
    origin_bag[0] = HEAD;
    origin_bag[1] = CODE_FALSE_REQUEST;
    origin_bag[3] = END;
    origin_bag[2] = origin_bag[0] - origin_bag[1] - origin_bag[3];
    origin_bag[4] = '\0';
    bag = build_data(FALSE_REQUEST);
    printf("FALSE_REQUEST:\n");
    printf("after build bag : %s\n", bag);
    printf("the effect you want to achieve:%s\n", origin_bag);
    if (!strcmp(bag, origin_bag)) {
        printf("FALSE_REQUEST match\n");
    }
    /*analysis_data*/
    printf("analysis_data\n");
    bag_type = analysis_data(bag);
    printf("ideal analysis result is %d\n", FALSE_REQUEST);
    printf("reality analysis result is %d\n\n", bag_type);
#endif

#if TEST_PROCESS
    /*测试运行流程*/
    int is_break_outside = FALSE;
    int state = BAG_REVICE;
    int bag_type = REQUEST;
    char *send_data;
    char *get_data = (char *)malloc(BAG_DATA * sizeof(char));
    int is_revice_success;
    int is_verify;

    while (is_break_outside != TRUE) {
        switch (state) {
            case BAG_BUILD :
                send_data = build_data(bag_type);
                if (!send_data) {
                    break;
                } else {
                    state = BAG_SEND;
                    break;
                }
            case BAG_SEND :
                bag_type = analysis_data(send_data);
                printf("want to send bag is:%d\n", bag_type);
                if (bag_type == ACK_DATA) {
                    is_break_outside = TRUE;
                    break;
                }

                state = BAG_REVICE;
                break;
            case BAG_REVICE :
                /* 在发送响应包、数据接收失败或成功后，接收数据包 */
                /* 其他情况接收命令包 */
                if (bag_type == RESPONSE || bag_type == FALSE_DATA ||
                    bag_type == ACK_DATA) {
#ifdef _REVICE_ERROR_DATA
                    /* 接收错误数据 */
                    get_data[0] = (0x04);
                    get_data[1] = CODE_NORMAL;
                    get_data[2] = 'h';
                    get_data[3] = 'i';
                    get_data[5] = END;
                    get_data[4] = get_data[0] - get_data[1] - get_data[2] -
                                    get_data[3] - get_data[5];
                    get_data[6] = '\0';
#else
                    /* 模拟接收数据 */
                    get_data = build_data(PRINT_NORMAL);
#endif
                } else {
#ifdef _REVICE_ERROR_REQUEST
                    /* 模拟接收错误的请求包 */
                    get_data[0] = HEAD;
                    get_data[1] = CODE_REQUEST;
                    get_data[3] = (0x54);
                    get_data[2] = get_data[0] - get_data[1] - get_data[3];
                    get_data[4] = '\0';
#else
                    /* 模拟接收请求包 */
                    get_data = build_data(REQUEST);
#endif
                }
                state = BAG_ANALYSIS;
                break;
            /* 这个和状态转换有关,需要根据自己的状态转换和逻辑来写 */
            case BAG_ANALYSIS :
                is_verify = analysis_verify(get_data);
                if (is_verify == FALSE) {
                    /* 请求包接收失败 */
                    if (bag_type == REQUEST) {
                        bag_type = FALSE_REQUEST;
                    } else if (bag_type == RESPONSE) {
                        /* 数据接收失败，发送数据接收失败的指令 */
                        bag_type = FALSE_DATA;
                    }

                    state = BAG_BUILD;
                    break;
                }

                is_revice_success = analysis_data(get_data);
                if (is_revice_success == FALSE) {
                    /* 请求包接收失败,发送请求包失败命令 */
                    if (bag_type == REQUEST) {
                        bag_type = FALSE_REQUEST;
                    }

                    /* 数据接收失败，发送数据接收失败的指令 */
                    if (bag_type == RESPONSE) {
                        bag_type = FALSE_DATA;
                    }

                    state = BAG_BUILD;
                    break;
                } else {
                    /* 请求包接收成功,发送应答包 */
                    if (bag_type == REQUEST) {
                        if (is_revice_success == REQUEST) {
                            bag_type = RESPONSE;
                        }
                    }

                    /* 数据接收成功，发送数据接收成功的指令 */
                    if (bag_type == RESPONSE) {
                        if (is_revice_success == PRINT_NORMAL) {
                            bag_type = ACK_DATA;
                        }
                    }

                    state = BAG_BUILD;
                    break;
                }
            case FINISH :
                is_break_outside = TRUE;
                break;
        }
    }

#endif
    return 1;
}